package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Id int
	Name string
	Age int
}

func (u User) Hello(){
	fmt.Println("hello world.")
}

func (u User) Hello2(name string) string{
	fmt.Println("hello,", name, " , my name is ", u.Name)
	return name
}

type Manager struct {
	User
	title string
}


func main() {
	u:= User{1,"OK",12}
	info(&u)
	info(u)

	m:= Manager{User:User{1,"ok",14}, title:"123"}
	t:= reflect.TypeOf(m)

	fmt.Println(t.Field(1))
	fmt.Println(t.FieldByIndex([]int{0,0}))


	v:=reflect.ValueOf(u)
	mv:=v.MethodByName("Hello2")
	args:=[]reflect.Value{reflect.ValueOf("joe")}
	result := mv.Call(args)
	fmt.Println(result)
	}

func info(o interface{}){
	t:= reflect.TypeOf(o)
	fmt.Println("Type:", t.Name())
	if k:=t.Kind(); k!=reflect.Struct{
		return
	}
	v:= reflect.ValueOf(o)
	fmt.Println("Fileds")
	for i:=0; i<t.NumField();i++{
		f := t.Field(i)
		val := v.Field(i).Interface()
		fmt.Println(f.Name,f.Type,val)
	}
	for i:=0; i<t.NumMethod(); i++{
		m:= t.Method(i)
		fmt.Println(m.Name, m.Type)
	}
}

func Set(o interface{}){
	v := reflect.ValueOf(o)
	if v.Kind()==reflect.Ptr && !v.Elem().CanSet(){
		fmt.Println("xxxx")
		return
	}else{
		v = v.Elem()
	}

	f:=v.FieldByName("Name")
	if !f.IsValid(){
		fmt.Println("BAO")
		return
	}
}